package testtiles.object;

import java.awt.Color;
import java.awt.Graphics2D;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;

import testtiles.Globals;

import butines.core.game.ImageSheet;
import butines.core.game.Input;
import butines.core.game.UIComponent;
import butines.core.game.UIListener;
import butines.core.math2d.Vector2D;
import butines.game.AbstractGameObject;
import butines.game.GameObjectMoving;
import butines.game.Messenger;
import butines.game.TileSet;
import butines.game.steering.LocalityQueryFacility;
import butines.game.steering.ProximityDatabase;

public class UIWorld extends UIComponent implements UIListener {

	private ProximityDatabase<GameObjectMoving> proximityDatabase; 
	private TileSet tileSet;
	
	private Messenger messenger = new Messenger();
	
	private ArrayList<Unit> visibledUnits = new ArrayList<Unit>();
	
	private Player player0 = new Player(this);
	private Player player1 = new Player(this);
	
	private BarView health = new BarView(32, 4);
	
	public UIWorld() {
		setScrollKeyboardEnabled(true);
		setScrollMouseEnabled(true);
		setIgnoreDrag(false);
		addListener(this);
	}
	
	public void init(ImageSheet terran, int numTileX, int numTileY) {
		int width = terran.getImageWidth() * numTileX;
		int height = terran.getImageHeight() * numTileY;
		
		tileSet = new TileSet(terran, numTileX, numTileY);
		tileSet.onScroll(0, 0, width, height);
		
		proximityDatabase = new LocalityQueryFacility<GameObjectMoving>(0, 0, width, height, numTileX/4, numTileY/4);
		
		setInnerSize(width, height);
			
		requestFocus();
	}
	
	public ProximityDatabase<GameObjectMoving> getProximityDatabase() {
		return proximityDatabase;
	}
	
	public Player getPlayer0() {
		return player0;
	}

	public Player getPlayer1() {
		return player1;
	}

	public TileSet getTileSet() {
		return tileSet;
	}
	
	private void updateUnits(float tpf) {
		// Update per Frame
		visibledUnits.clear();

		player0.updateUnits(visibledUnits, tpf);
		player1.updateUnits(visibledUnits, tpf);
		
	}
	
	private void drawCicle(Graphics2D g2d, Vector2D pos, float radius) {
		int r = Math.round(radius);
		int x = Math.round(pos.x);
		int y = Math.round(pos.y);
		g2d.drawOval(x-r, y-r, r*2, r*2);
	}
	
	private void drawLine(Graphics2D g2d, Vector2D a, Vector2D b) {
		int ax = Math.round(a.x);
		int ay = Math.round(a.y);
		int bx = Math.round(b.x);
		int by = Math.round(b.y);
		g2d.drawLine(ax, ay, bx, by);
	}
	
	private void drawStringCenter(Graphics2D g2d, float x, float y, String str) {
		int w = g2d.getFontMetrics().stringWidth(str);
		g2d.drawString(str, x - w / 2, y);
	}
	
	private void drawUnits(Graphics2D g2d) {
		Collections.sort(visibledUnits, AbstractGameObject.DRAW_ORDER);

		for (Unit obj: visibledUnits) {
			if (obj.isMouseOver()) {
				g2d.setColor(Color.YELLOW);
				drawCicle(g2d, obj.getPosition(), 16);
			}
			if (obj.isSelected()) {
				g2d.setColor(Color.GREEN);
				drawCicle(g2d, obj.getPosition(), 18);
			}
		}

		for (AbstractGameObject obj: visibledUnits) {
			obj.draw(g2d);
		}
		
		for (Unit obj: visibledUnits) {
			health.draw(g2d, obj.getPosition(), obj.getStatus().getHealth(), obj.getStatus().getMaxHealth());
		}
	
		if (Globals.debug.value() > 0) {
			for (Unit unit: visibledUnits) {
				debug(g2d, unit);
			}
		}
	}
		
	public Messenger getMessenger() {
		return messenger;
	}
	
	public void clear(Graphics2D g2d, Color color) {
		g2d.setColor(color);
		g2d.fillRect(Math.round(getOffsetX()), Math.round(getOffsetY()), getWidth(), getHeight());
	}
	
	public void onUpdate(float tpf) {
		float frameTime = getGameContext().getFrameTime();
		
		messenger.dispatchMessages(frameTime);
		
		updateUnits(tpf);
		
	}
	
	public void onRender(Graphics2D g2d) {
		
		clear(g2d, Color.gray);
		
		tileSet.draw(g2d);
		
		drawUnits(g2d);
		
	}
	
	public void onFocus(boolean focus) {
		
	}

	public void onSelect(float x, float y, float w, float h) {
		player0.selectUnits();
	}

	public void onKey(int keyCode, boolean pressed) {
		if (keyCode == Input.KEY_H && pressed) {
			player0.commandHoldUnit();
		}
		if (keyCode == Input.KEY_D && pressed) {
			float v = Globals.debug.getValue() == 0 ? 1 : 0;
			 Globals.debug.setValue(v);
		}
	}

	public void onButton(float x, float y, int button, boolean pressed) {
		if (button == Input.BUTTON_3 && pressed) {
			player0.commandMoveUnit((int)x, (int)y);
		}
	}

	public void onMove(float x, float y, float dx, float dy) {

	}

	public void onMouseOver(boolean mouseOver) {
		
	}
	
	public void onScroll(float ox, float oy, int vw, int vh) {
		tileSet.onScroll(ox, oy, vw, vh);
	}
	
	private class BarView {

		private Color colorEmpty = Color.red;
		private Color colorFilled = Color.green;
		private int width = 32;
		private int height = 4;
		
		private float offsetX = 0;
		private float offsetY = -24;
		
		public BarView(int width, int height) {
			this.width = width;
			this.height = height;
		}

		public void draw(Graphics2D g, Vector2D pos, float cur, float max) {
			float x = (pos.x - width / 2f) + offsetX;
			float y = pos.y + offsetY;
			int drawX = Math.round(x);
			int drawY = Math.round(y);
			int filled = Math.round(width * (cur/max));
			
			g.setColor(colorFilled);
			g.fillRect(drawX, drawY, filled, height);
			
			if (filled < width) {
				g.setColor(colorEmpty);
				g.fillRect(drawX + filled, drawY, width - filled, height);
			}
			
			g.setColor(Color.black);
			g.drawRect(drawX-1, drawY-1, width+1, height+1);
			
		}
		
	}
	
	private void debug(Graphics2D g2d, Unit unit) {
		g2d.setColor(Color.YELLOW);
		
		Vector2D sf = unit.getVelocity().copy();
		sf.mult(unit.getRadius() * 2);
		sf.add(unit.getPosition());
		drawLine(g2d, unit.getPosition(), sf);
		
		g2d.setColor(Color.GREEN);
		sf = unit.getAccel().copy();
		sf.mult(unit.getRadius() * 10);
		sf.add(unit.getPosition());
		drawLine(g2d, unit.getPosition(), sf);
		
		g2d.setColor(Color.RED);
		drawCicle(g2d, unit.getPosition(), unit.getRadius());
		
		g2d.setColor(Color.PINK);
		drawCicle(g2d, unit.getPosition(), unit.getViewDistance());
		
		g2d.setColor(Color.WHITE);
		float x = unit.getPosition().x;
		float y = unit.getPosition().y;
		drawStringCenter(g2d, x, y-10, "ID:" + unit.getId());
		drawStringCenter(g2d, x, y, 
				MessageFormat.format("SP:{0,number,#.##}", unit.getSpeed()));
		
		x = unit.getTargetPoint().x;
		y = unit.getTargetPoint().y;
		g2d.setColor(Color.BLUE);
		drawStringCenter(g2d, x, y-10, "ID:" + unit.getId());
		

	}
	
}
